package com.example.myapplication.view

import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.LayoutRes
import androidx.recyclerview.widget.RecyclerView
import com.example.myapplication.R

/**
 * RecyclerView的适配器
 */
abstract class SimpleRecyclerAdapter<Data> :
    RecyclerView.Adapter<SimpleRecyclerAdapter.SimpleViewHolder<Data>>,
    View.OnClickListener,
    View.OnLongClickListener,
    AdapterCallback<Data> {

    var mDataList: MutableList<Data>
    var listener: AdapterListener<Data>? = null
    val childStateChangeListener = object : RecyclerView.OnChildAttachStateChangeListener {
        override fun onChildViewAttachedToWindow(view: View) {
            (view.getTag(R.id.tag_recycler_holder) as SimpleViewHolder<*>).attachedToWindow(view)
        }

        override fun onChildViewDetachedFromWindow(view: View) {
            (view.getTag(R.id.tag_recycler_holder) as SimpleViewHolder<*>).detachedFromWindow(view)
        }
    }

    constructor() : this(null)

    constructor(listener: AdapterListener<Data>?) : this(listOf<Data>(), listener)

    constructor(list: List<Data>, listener: AdapterListener<Data>?) : super() {
        this.listener = listener
        this.mDataList = mutableListOf()
        this.mDataList.addAll(list)
    }

    override fun getItemCount(): Int = mDataList.size

    fun getItems(): MutableList<Data> {
        return mDataList
    }

    fun getTag(): Int {
        return R.id.tag_recycler_holder
    }

    fun add(data: Data) {
        mDataList.add(data)
        notifyItemInserted(mDataList.size - 1)
    }

    fun addAll(vararg data: Data) {
        if (data.isNotEmpty()) {
            val start = mDataList.size
            val offSet = data.size
            mDataList.addAll(data)
            notifyItemRangeChanged(start, offSet)
        }
    }

    fun addAll(collection: Collection<Data>) {
        if (collection.isNotEmpty()) {
            val start = mDataList.size
            val offSet = collection.size
            mDataList.addAll(collection)
            notifyItemRangeChanged(start, offSet)
        }
    }

    fun clear() {
        mDataList.clear()
        notifyDataSetChanged()
    }

    fun replaceAll(vararg data: Data) {
        if (data.isNotEmpty()) {
            mDataList.clear()
            mDataList.addAll(data)
            notifyDataSetChanged()
        }
    }

    fun replaceAll(collection: Collection<Data>) {
        if (collection.isNotEmpty()) {
            mDataList.clear()
            mDataList.addAll(collection)
            notifyDataSetChanged()
        }
    }

    fun replace(position: Int, data: Data) {
        val size = mDataList.size
        if (position in 0 until size) {
            // 进行数据的移除
            mDataList.removeAt(position)
            //更新
            mDataList.add(position, data)
            // 通知这个坐标下的数据有更新
            notifyItemChanged(position)
        }
    }

    override fun update(data: Data, viewHolder: SimpleViewHolder<Data>) {
        // 得到当前ViewHolder的坐标
        val pos: Int = viewHolder.adapterPosition
        if (pos >= 0) {
            replace(pos, data)
        }
    }

    override fun getItemViewType(position: Int): Int {
        return getItemViewType(position, mDataList.get(position))
    }

    /**
     * 返回XML的id,用作创建ViewHolder
     */
    @LayoutRes
    abstract fun getItemViewType(position: Int, data: Data): Int

    /**
     * 约定viewType 为自定义的XML布局
     */
    final override fun onCreateViewHolder(
        parent: ViewGroup,
        viewType: Int
    ): SimpleViewHolder<Data> {
        val inflate = LayoutInflater.from(parent.context).inflate(viewType, parent, false)
        val viewHolder = onCreateViewHolder(inflate, viewType)
        inflate.setTag(R.id.tag_recycler_holder, viewHolder)
        inflate.setOnClickListener(this)
        inflate.setOnLongClickListener(this)
        viewHolder.callback = this
        return viewHolder
    }

    override fun onBindViewHolder(holder: SimpleViewHolder<Data>, position: Int) {
        holder.bind(mDataList[position])
    }

    override fun onClick(view: View?) {
        val viewHolder =
            view?.getTag(R.id.tag_recycler_holder)?.let { it as SimpleViewHolder<Data> }
                ?: return
        listener?.onItemClick(viewHolder, mDataList[viewHolder.adapterPosition])
    }

    override fun onLongClick(view: View?): Boolean {
        val viewHolder =
            view?.getTag(R.id.tag_recycler_holder)?.let { it as SimpleViewHolder<Data> }
                ?: return false
        return listener?.onItemLongClick(viewHolder, mDataList[viewHolder.adapterPosition])
            ?: false
    }

    abstract fun onCreateViewHolder(contentView: View, viewType: Int): SimpleViewHolder<Data>


    interface AdapterListener<Data> {
        fun onItemClick(viewHolder: SimpleViewHolder<Data>, data: Data)
        fun onItemLongClick(viewHolder: SimpleViewHolder<Data>, data: Data): Boolean
    }

    abstract class SimpleViewHolder<Data>(itemView: View) : RecyclerView.ViewHolder(itemView) {

        var mData: Data? = null
        var callback: AdapterCallback<Data>? = null

        fun bind(data: Data) {
            onBindView(data, this.mData)
            this.mData = data
        }

        abstract fun onBindView(newData: Data, oldData: Data?)

        open fun updateData(data: Data) {
            callback?.update(data, this)
        }

        open fun attachedToWindow(view: View) {
        }

        open fun detachedFromWindow(view: View) {
        }

        fun <T> equalToUpdataUI(newValue: T?, oldValue: T?, block: (T) -> Unit) {
            val isSame = newValue?.equals(oldValue) ?: return
            if (isSame) return
            block.invoke(newValue)
        }
    }

}

